LAB 3: Image Bitwise Logical Operators

Adding a Logo to an Image Using Bitwise Operators

Instructions: Choose two images: one will be a background (e.g. a photograph or a poster) and the other will be a foreground (e.g. a logo, a banner, or a text image) to be overlaid on top of the background. In coding, we will use bg for background and fg for foreground. Be creative when choosing your combination of foreground and background images. Suggestion: pick a foreground with a relatively clean backdrop (see ours; yours must be a different one).
ToDo: While sample output of every step is provided, only partial code is given, it is your job to fill in the rest. Apply the knowledge you have learned from the lecture as well as your experiences from Lab1 and Lab2.
PLEASE NOTE: In the lecture, we consider two cases of processing a robot image: one with black background and the other white. Correspondingly, in this lab you may choose a foreground image that has either dark or bright backdrop. Both are okay. So we make it clear for both cases, in the following we will show you examples of both (you only need to do one). The sample output for every exercise will first presented the result of a dark-backdrop case, followed by the bright-backdrop case.

In this lab exercise, we make use of user-defined functions in order to display the actual size of an image while fitting it to the screen boundaries. We provide two functions: one for displaying a single image and the other for displaying two images side-by-side. Here are the code and sample usages of these functions are presented below.

In [2]:
def get_figsize(im):
    # What size does the figure need to be in inches to fit the image?
    dpi = plt.rcParams['figure.dpi']
    dim = im.shape
    figuresize = dim[1]/float(dpi), dim[0]/float(dpi)
    return(figuresize)
In [3]:
def display_image_actual_size_single(im_data):
    figuresize = get_figsize(im_data)
    # Create a figure of the right size with one axes that takes up the full figure
    fig = plt.figure(figsize=figuresize)
    # Add the single axis to fit the image to the screen boundary
    ax = fig.add_axes([0, 0, 1, 1])
    ax.imshow(im_data, cmap='gray')
    ax.axis('off')
    plt.show()
    return(fig)
In [4]:
def display_image_actual_size_double(im_data1,im_data2):
    # assuming that the two input images have the same dimension and shape
    # then, we calculate figsize from one of the two images
    figuresize = get_figsize(im_data1)
    # Create a figure of the right size that can accommodate two images side-by-side
    fig = plt.figure(figsize=(figuresize[0],figuresize[1]*2+.1))
    ax1 = fig.add_axes([0,0,1,1])
    ax1.imshow(im_data1, cmap='gray')
    ax1.axis('off')
    ax2 = fig.add_axes([1.1,0,1,1])
    ax2.imshow(im_data2, cmap='gray')
    ax2.axis('off')
    return(fig)

Load and display selected images

First, let us look at our background and foreground images that we have chosen. Load them into your Python enviroment and display them. The code here illustrates how to use both of our user-defined image-display functions. Also, we show you two foreground cases (as noted above); you need only one.

In [5]:
fig = display_image_actual_size_single(bg)
fig = display_image_actual_size_double(fgD, fgB)

Identify a region of interest on a background image

Decide where on the background you want to put your foreground image. Cut from the background this region of interest (roi); it is of the same width, same height, and same color channels as the foreground image. For example, in our case here, we will put the logo at the bottom right of our poster. The logo's top-left corner will be at the coordinate (row=390, column=765) of the poster. Remember image axes? Row 0 is at the top.

In [ ]:
rows, cols, channels = fg.shape       #get the width, the height, and the channels of fg
roi = bg[390:390+rows, 765:765+cols]  #cut from bg the roi of the same dimesions as fg
Notice: How to assess a specific region on an image. This is essentially array indexing in Python.
Exercise #1: Get the region of interest (roi). Display side-by-side your foreground and the roi. Shown below -- Top: sample output for a foreground with dark backdrop. Bottom: output for a foreground with bright backdrop.

Create a binary mask of a foreground

Following the lecture where we create a black-and-white image of a robot, we first convert the foreground image to grayscale, named it fgGrayscale. Then, we threshold it using OpenCV threshold function (provided below). It returns two outputs, the thresholded image is the latter. The second variable thres is your threshold.

In [ ]:
retval, mask = cv2.threshold(fgGrayscale, thres, 255, cv2.THRESH_BINARY)
ToDo: use the internet to learn more about cv2.threshold so you can effectively adapt it to your own image.
Exercise #2: Create a binary mask of your foreground image. Display side-by-side your foreground in grayscale and the resulting binary mask after thresholding. Shown below -- Top: example output for the case of a foreground with dark backdrop. Bottom: example output for the case of a foreground with bright backdrop.

Mask the foreground and the roi, then combine them

The next steps involves applying one or more bitwise operations, making use of the binary mask we have just created. We give you the expected output; it is your task to figure out the process. Below is an OpenCV command for 'and' operation. The syntax of other bitwise operations are the same (consult OpenCV library to learn more).

In [ ]:
result = cv2.bitwise_and(img, mask)
Caution: To perform bitwise operations, OpenCV requires that both inputs are of the same dimension. You need to make your grayscale and/or binary mask a color image.
Exercise #3: Mask the foreground (removing the backdrop of the logo). Display your binary mask along with the resulting image. Again, we show you two versions of the output for dark and bright foreground.
Exercise #4: Mask the roi (deleting pixels that will be replaced by the logo). Display both the mask and the result.
Exercise #5: Combine foreground and roi (putting the logo onto the roi). Display and save your combined roi.

Put the processed roi back onto the original background image

Exercise #6: Put roi (now with the logo) back onto the original background. Display and save your result.